﻿#pragma once
/**
@author 何炜
@date 2011/4/27
@brief .
@details
*/

namespace GLL
{

#define Combo_Bit2Mov ((sizeof(combo) - sizeof(master)) * 8)

	template<typename combo, typename master, typename slave>
	combo POS_t_MakePos(master type, slave index){ return (combo(type) << Combo_Bit2Mov)| combo(index); }

	template<typename combo, typename master>
	master POS_t_GetType(combo GlobalPos){ return master(GlobalPos >> Combo_Bit2Mov); }

	template<typename combo, typename slave>
	slave POS_t_GetIdx(combo GlobalPos){ return slave( GlobalPos & (combo(0) |  slave(-1)) );}

	struct POS_Int64_Hash
	{
		template<typename master, typename slave>
		static size_t get(const master& m, const slave& s)
		{
			return POS_t_MakePos<size_t, uint, uint>(uint(m), uint(s));
		}
	};

	/**2合1 数据类型.
	可以将两个原始类型(master_t,  slaveType)合并为一个原始类型(ComboType)使用的类
	@tparam combo 组合后的类型，大小必须是 master + slave
	@tparam master 主类型
	@tparam slave 副类型
	*/
	template
		<
		typename combo, 
		typename master, 
		typename slave, 
		typename hash_function = POS_Int64_Hash,
		master invalied_type = master(), 
		slave invalied_idx=slave()
		>
	class Combo2In1
	{
	public:
		typedef combo combo_t;
		typedef master master_t; 
		typedef slave slave_t;

		master_t type;
		slave_t index;
		combo_t AsPos() const{return POS_t_MakePos<combo_t, master_t, slave_t>(type, index);}
		Combo2In1(){Reset();}
		void Reset(){type = invalied_type; index = invalied_idx;}
		Combo2In1(combo_t pos)
		{
			type = POS_t_GetType<combo_t, master_t>(pos);
			index = POS_t_GetIdx<combo_t, slave_t>(pos);
		}
		Combo2In1(master_t _type, slave_t _index){type = _type; index = _index;}
		Combo2In1(const Combo2In1& p){type = p.type;index = p.index;}
		//简单判断槽是否有效
		bool IsValid() const {return !(type == invalied_idx || index == invalied_idx);}
		master_t InvalidType() const {return invalied_type;}
		slave_t InvalidIndex() const {return invalied_idx;}
		bool operator ==(const Combo2In1& rv) const {
			return ((type == rv.type) && (index == rv.index));
		}
		bool operator < (const Combo2In1& rv) const
		{
			if(type != rv.type) return type < rv.type;
			return index < rv.index;
		}
		size_t GetHash() const {return hash_function::get(type, index);}
		operator size_t() const {return hash_function::get(type, index);}
	};


};//GLL
